package bma.common.netty.thrift.dual.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.thrift.TApplicationException;
import org.apache.thrift.protocol.TMessage;

import bma.common.langutil.ai.stack.AIStack;
import bma.common.langutil.core.ValueUtil;
import bma.common.netty.thrift.dual.NTSDispatcher;
import bma.common.netty.thrift.dual.NTSProcessor;
import bma.common.netty.thrift.dual.NTSRequest;

public class NTSDispatcherCommon implements NTSDispatcher, NTSProcessor {

	protected Map<String, NTSProcessor> moduleMap = new HashMap<String, NTSProcessor>();
	protected Map<String, NTSProcessor> methodMap = new HashMap<String, NTSProcessor>();

	public void setServices(List<NTSModuleProcessor> services) {
		for (NTSModuleProcessor s : services) {
			if (ValueUtil.notEmpty(s.getModule())) {
				moduleMap.put(s.getModule(), s);
			}
			if (s instanceof NTSBaseProcessor) {
				NTSBaseProcessor bs = (NTSBaseProcessor) s;
				Set<String> ms = bs.listMethodsNames();
				for (String n : ms) {
					if (methodMap.containsKey(n))
						throw new IllegalArgumentException("thrift method[" + n
								+ "] conflict");
					methodMap.put(n, s);
				}
			}
		}
	}

	protected NTSProcessor getProcessor(String name, NTSRequest req) {
		String module = null;
		int idx = name.indexOf('.');
		if (idx != -1) {
			module = name.substring(0, idx);
			name = name.substring(idx + 1);
			TMessage msg = req.getHeader();
			TMessage newMsg = new TMessage(name, msg.type, msg.seqid);
			req.setHeader(newMsg);
		}
		if (module == null) {
			NTSProcessor p = methodMap.get(name);
			if (p != null) {
				return p;
			}
		}
		return moduleMap.get(module);
	}

	@Override
	public boolean dispatch(AIStack<NTSProcessor> stack, String name,
			NTSRequest req) {
		NTSProcessor p = getProcessor(name, req);
		return stack.success(p);
	}

	@Override
	public boolean process(NTSRequest req) {
		String name = req.getHeader().name;
		NTSProcessor p = getProcessor(name, req);
		if (p == null) {
			req.end(null, new TApplicationException(
					TApplicationException.UNKNOWN_METHOD, "'" + name
							+ "' miss processor"));
		}
		return p.process(req);
	}

}
